home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / WWW / apache_1.0.5 / support / logresolve.c < prev    next >
C/C++ Source or Header  |  1996-02-16  |  7KB  |  273 lines

  1. /***                                                                      ***\
  2.  
  3.     logresolve 1.0
  4.  
  5.     Tom Rathborne - tomr@uunet.ca - http://www.uunet.ca/~tomr/
  6.     UUNET Canada, April 16, 1995
  7.  
  8.     Usage: logresolve [arguments] < access_log > new_log
  9.  
  10.     Arguments: if you give any arguments, statistics are printed to STDERR.
  11.  
  12.     Notes:
  13.  
  14.     To generate meaningful statistics from an HTTPD log file, it's good
  15.     to have the domain name of each machine that accessed your site, but
  16.     doing this on the fly can slow HTTPD down.
  17.  
  18.     Compiling NCSA HTTPD with the -DMINIMAL_DNS flag turns IP#->hostname
  19.     resolution off. Before running your stats program, just run your log
  20.     file through this program (logresolve) and all of your IP numbers will
  21.     be resolved into hostnames (where possible).
  22.  
  23.     logresolve takes an HTTPD access log (in the COMMON log file format,
  24.     or any other format that has the IP number/domain name as the first
  25.     field for that matter), and outputs the same file with all of the
  26.     domain names looked up. Where no domain name can be found, the IP
  27.     number is left in.
  28.  
  29.     To minimize impact on your nameserver, logresolve has its very own
  30.     internal hash-table cache. This means that each IP number will only
  31.     be looked up the first time it is found in the log file. As noted
  32.     above, giving any command-line arguments to logresolve (anything at
  33.     all!) will give you some statistics on the log file and the cache,
  34.     printed to STDERR.
  35.  
  36. \***                                                                      ***/
  37.  
  38. #include <sys/types.h>
  39. #include <sys/socket.h>
  40. #include <netdb.h>
  41. #include <string.h>
  42. #include <stdio.h>
  43.  
  44. /* maximum line length */
  45. #define MAXLINE 1024
  46.  
  47. /* maximum length of an IP number as a string */
  48. #define IPSTRLEN 16
  49.  
  50. /* number of buckets in cache hash table */
  51. #define BUCKETS 256
  52.  
  53. /*
  54.  * struct nsrec - record of nameservice for cache linked list
  55.  * 
  56.  * ipnum - IP number hostname - hostname noname - nonzero if IP number has no
  57.  * hostname, i.e. hostname=IP number
  58.  */
  59.  
  60. struct nsrec {
  61.     unsigned char   ipnum[4];
  62.     char           *hostname;
  63.     int             noname;
  64.     struct nsrec   *next;
  65. }              *nscache[BUCKETS];
  66.  
  67. /*
  68.  * statistics - obvious
  69.  */
  70.  
  71. int             cachehits = 0;
  72. int             cachesize = 0;
  73. int             entries = 0;
  74. int             resolves = 0;
  75. int             withname = 0;
  76. int             yucky = 0;
  77. int             noname = 0;
  78.  
  79. /*
  80.  * ipsame - takes two IP numbers and returns TRUE if they're the same
  81.  */
  82.  
  83. int
  84. ipsame(ipnum1, ipnum2)
  85.     unsigned char   ipnum1[4];
  86.     unsigned char   ipnum2[4];
  87. {
  88.     return (ipnum1[0] == ipnum2[0]
  89.         && ipnum1[1] == ipnum2[1]
  90.         && ipnum1[2] == ipnum2[2]
  91.         && ipnum1[3] == ipnum2[3]);
  92. }
  93.  
  94. /*
  95.  * ipbuild - makes an IP number char array from 4 integers
  96.  */
  97.  
  98. ipbuild(ipnum, a, b, c, d)
  99.     unsigned char   ipnum[4];
  100.     unsigned int    a, b, c, d;
  101. {
  102.     ipnum[0] = a;
  103.     ipnum[1] = b;
  104.     ipnum[2] = c;
  105.     ipnum[3] = d;
  106. }
  107.  
  108. /*
  109.  * ipstr - converts an IP number to a string
  110.  */
  111.  
  112. char           *
  113. ipstr(string, ipnum)
  114.     char           *string;
  115.     unsigned char   ipnum[4];
  116. {
  117.     sprintf(string, "%d.%d.%d.%d", ipnum[0], ipnum[1], ipnum[2], ipnum[3]);
  118.     return (string);
  119. }
  120.  
  121. /*
  122.  * cgethost - gets hostname by IP address, caching, and adding unresolvable
  123.  * IP numbers with their IP number as hostname, setting noname flag
  124.  */
  125.  
  126. cgethost(string, ipnum)
  127.     char           *string;
  128.     unsigned char   ipnum[4];
  129. {
  130.     struct nsrec   *current;
  131.     struct hostent *hostdata;
  132.  
  133.     current = nscache[((ipnum[0] + ipnum[1] + ipnum[2] + ipnum[3]) % BUCKETS)];
  134.  
  135.     while (current->next && !ipsame(ipnum, current->next->ipnum))
  136.         current = current->next;
  137.  
  138.     if (!current->next) {
  139.         cachesize++;
  140.         current->next = (struct nsrec *) malloc(sizeof(struct nsrec));
  141.         current = current->next;
  142.         current->next = 0;
  143.         current->noname = 0;
  144.  
  145.         current->ipnum[0] = ipnum[0];
  146.         current->ipnum[1] = ipnum[1];
  147.         current->ipnum[2] = ipnum[2];
  148.         current->ipnum[3] = ipnum[3];
  149.  
  150.         if (hostdata = gethostbyaddr((const char *) ipnum, 4, AF_INET)) {
  151.             current->hostname = (char *) malloc(strlen(hostdata->h_name) + 1);
  152.             strcpy(current->hostname, hostdata->h_name);
  153.         } else {
  154.             noname++;
  155.             current->noname = 1;
  156.             current->hostname = (char *) malloc(IPSTRLEN);
  157.             ipstr(current->hostname, current->ipnum);
  158.         }
  159.     } else {
  160.         current = current->next;
  161.         cachehits++;
  162.     }
  163.     strcpy(string, current->hostname);
  164. }
  165.  
  166. /*
  167.  * gets a line from stdin
  168.  */
  169.  
  170. int
  171. getline(s, n)
  172.     char           *s;
  173.     int             n;
  174. {
  175.     char           *cp;
  176.  
  177.     if (!fgets(s, n, stdin))
  178.         return (1);
  179.     if (cp = strchr(s, '\n'))
  180.         *cp = '\0';
  181.     return (0);
  182. }
  183.  
  184. /*
  185.  * prints various statistics to output
  186.  */
  187.  
  188. stats(output)
  189.     FILE           *output;
  190. {
  191.     int             i, ipstring[IPSTRLEN];
  192.     struct nsrec   *current;
  193.  
  194.     fprintf(output, "logresolve Statistics:\n");
  195.  
  196.     fprintf(output, "Entries: %d\n", entries);
  197.     fprintf(output, "    With name : %d\n", withname);
  198.     fprintf(output, "    Resolves  : %d\n", resolves);
  199.     fprintf(output, "    - Yucky   : %d\n", yucky);
  200.     fprintf(output, "    - No name : %d\n", noname);
  201.     fprintf(output, "Cache hits    : %d\n", cachehits);
  202.     fprintf(output, "Cache size    : %d\n", cachesize);
  203.     fprintf(output, "Cache buckets :     IP number * hostname\n");
  204.  
  205.     for (i = 0; i < BUCKETS; i++) {
  206.         current = nscache[i];
  207.         while (current->next) {
  208.             ipstr(ipstring, current->next->ipnum);
  209.             if (current->next->noname)
  210.                 fprintf(output, "         %3d  %15s ! %s\n", i, ipstring, current->next->hostname);
  211.             else
  212.                 fprintf(output, "         %3d  %15s - %s\n", i, ipstring, current->next->hostname);
  213.             current = current->next;
  214.         }
  215.     }
  216. }
  217.  
  218.  
  219. int
  220. main(argc, argv)
  221.     int             argc;
  222.     char           *argv[];
  223. {
  224.     unsigned char   ipnum[4];
  225.     char           *foo, *bar, hoststring[MAXLINE], ipstring[IPSTRLEN], line[MAXLINE],
  226.                     nl[MAXLINE];
  227.     int             i, ip;
  228.  
  229.     for (i = 0; i < BUCKETS; i++) {
  230.         nscache[i] = (struct nsrec *) malloc(sizeof(struct nsrec));
  231.         nscache[i]->next = 0;
  232.         nscache[i]->noname = 0;
  233.     }
  234.  
  235.     while (!getline(line, MAXLINE) && *line) {
  236.         entries++;
  237.         if ((*line < '0') || (*line > '9')) {
  238.             printf("%s\n", line);
  239.             withname++;
  240.         } else {
  241.             resolves++;
  242.             ip = 1;
  243.             strcpy(nl, line);
  244.             foo = nl;
  245.             bar = nl;
  246.             for (i = 0; (i < 4) && ip; i++) {
  247.                 while (*bar != '.' && *bar != ' ')
  248.                     bar++;
  249.                 *bar = 0;
  250.                 ipnum[i] = atoi(foo);
  251.                 foo = ++bar;
  252.                 if (((*bar < '0') || (*bar > '9')) && i < 3)
  253.                     ip = 0;
  254.             }
  255.             if (ip) {
  256.                 cgethost(hoststring, ipnum);
  257.                 printf("%s %s\n", hoststring, bar);
  258.             } else {
  259.                 yucky++;
  260.                 printf("%s\n", line);
  261.             }
  262.         }
  263.     }
  264.  
  265.     if (--argc)
  266.         stats(stderr);
  267.  
  268.     return (0);
  269. }
  270. -- end
  271.  
  272.  
  273.